// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build js&&wasm 

package runtime

import (
	"unsafe"
)

// 不要拆分堆栈，因为在没有有效的G、
// 的情况下可能会调用此函数，这会阻止我们分配更多堆栈。
// go:nosplit 
func sysAlloc(n uintptr, sysStat *sysMemStat) unsafe.Pointer {
	p := sysReserve(nil, n)
	sysMap(p, n, sysStat)
	return p
}

func sysUnused(v unsafe.Pointer, n uintptr) {
}

func sysUsed(v unsafe.Pointer, n uintptr) {
}

func sysHugePage(v unsafe.Pointer, n uintptr) {
}

// 不要拆分堆栈，因为在没有有效的G、
// 的情况下可能会调用此函数，这会阻止我们分配更多堆栈。
// go:nosplit 
func sysFree(v unsafe.Pointer, n uintptr, sysStat *sysMemStat) {
	sysStat.add(-int64(n))
}

func sysFault(v unsafe.Pointer, n uintptr) {
}

var reserveEnd uintptr

func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
	// TODO（neelance）：可能与mem_plan9统一。go，取决于https:

	if v != nil {
		// WebAssembly线性内存的地址空间是连续的，因此不支持请求特定地址。我们可以使用
		// 一个不同的地址，但是mheap。sysAlloc立即丢弃结果
		// 并且我们不重用传递给sysFree的块。
		return nil
	}

	// 将初始reserveEnd四舍五入为64千字节，以便
	// 保留始终与页面大小对齐。
	initReserveEnd := alignUp(lastmoduledatap.end, physPageSize)
	if reserveEnd < initReserveEnd {
		reserveEnd = initReserveEnd
	}
	v = unsafe.Pointer(reserveEnd)
	reserveEnd += alignUp(n, physPageSize)

	current := currentMemory()
	// reserveEnd始终位于页面边界。
	needed := int32(reserveEnd / physPageSize)
	if current < needed {
		if growMemory(needed-current) == -1 {
			return nil
		}
		resetMemoryDataView()
	}

	return v
}

func currentMemory() int32
func growMemory(pages int32) int32

// resetMemoryDataView向JS前端发送信号，表示WebAssembly的内存。使用了grow指令。
// 这允许前端用新的DataView对象替换旧的DataView对象。
func resetMemoryDataView()

func sysMap(v unsafe.Pointer, n uintptr, sysStat *sysMemStat) {
	sysStat.add(int64(n))
}
